package band.wukong.practice.javase.core.regex;

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Desc: 初级正则
 * User: sunjs
 * Date: 2010-4-21 21:11:15
 */
public class JunirRegExp {
    public static void main(String[] args) {
//        aboutCharacterClasses();
//        aboutPredefinedCharacterClasses();
//        aboutGreedyQuantifiers();
//        aboutPosixCharacterClasses();
//        aboutBoundaryMatchers();
//        aboutMatchFindLookAt();
//        aboutStartEnd();
//        aboutReplace();
        aboutGroup();
    }

    /**
     * 关于字符类
     */
    private static void aboutCharacterClasses() {
        System.out.println("---------------basic");
        //范围。[]匹配一个字符，一个[]代表一位字符
        p("a".matches("[abc]"));    //abc之中的
        p("a".matches("[^abc]"));   //非abc

        p("A".matches("[a-zA-Z]"));     //a-z或A-Z
        p("A".matches("[a-z]|[A-Z]"));  //a-z或A-Z
        p("A".matches("[a-z[A-Z]]"));   //a-z或A-Z

        p("R".matches("[A-Z&&[RFG]]")); //A-Z之中并且是RFG之中的
    }

    /**
     * 关于预定义字符类
     */
    private static void aboutPredefinedCharacterClasses() {
        System.out.println("---------------basic");
        p("a".matches("."));    //任何字符（与行结束符可能匹配也可能不匹配）
        p("aa".matches("aa"));  //正常字符
        p("a".matches("\\d"));  //数字：[0-9]
        p("a".matches("\\D"));  //非数字： [^0-9]
        p(" ".matches("\\s"));  //空白字符：[ \t\n\x0B\f\r]
        p(" ".matches("\\S"));  //非空白字符：[^\s]
        p("a".matches("\\w"));  //单词字符：[a-zA-Z_0-9]
        p("a".matches("\\W"));  //非单词字符：[^\w]

        System.out.println("---------------advanced");
        p("a_8".matches("\\w{3}"));
        p("a-8".matches("\\w{3}"));
        p("abc888&^%".matches("[a-z]{1,3}\\d+[&^#%]+"));
        p("\\".matches("\\\\"));
        System.out.println("\\");
        System.out.println("\\\\");

    }

    /**
     * 关于量词
     */
    private static void aboutGreedyQuantifiers() {
        System.out.println("---------------X?");
        p("".matches("a?"));
        p("a".matches("a?"));
        p("aa".matches("a?"));

        System.out.println("---------------X*");
        p("".matches("a*"));
        p("a".matches("a*"));
        p("aa".matches("a*"));

        System.out.println("---------------X+");
        p("".matches("a+"));
        p("a".matches("a+"));
        p("aa".matches("a+"));

        System.out.println("---------------X{n}");
        p("".matches("a{1}"));
        p("a".matches("a{1}"));
        p("aa".matches("a{1}"));

        System.out.println("---------------X{n,}");
        p("".matches("a{1,}"));
        p("a".matches("a{1,}"));
        p("aa".matches("a{1,}"));

        System.out.println("---------------X{n,m}");
        p("".matches("a{1,2}"));
        p("a".matches("a{1,2}"));
        p("aa".matches("a{1,2}"));

        System.out.println("---------------More");
        p("2222222222".matches("\\d{3,10}"));
        p("192.168.0.1".matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
        p("192".matches("1[0-9][0-9]"));
    }

    /**
     * 关于POSIX字符类。POSIX是UNIX下的一套标准（缩写）
     */
    private static void aboutPosixCharacterClasses() {
        p("a".matches("\\p{Lower}"));
        p("aa".matches("\\p{Lower}"));
    }

    /**
     * 关于边界匹配(开头或结尾)
     */
    private static void aboutBoundaryMatchers() {
        System.out.println("---------------basic");
        p("hello sir".matches("^h.*")); //h开头，任意长度字符串
        p("hello sir".matches(".*ir$"));    //以ir结尾，任意长度字符串
        p("hello sir".matches("^h[a-z]{1,3}o\\b.*"));   // \b a word boundary
        p("hellosir".matches("^h[a-z]{1,3}o\\b.*"));

        System.out.println("---------------advanced");
        //whilte lines
        p(" \n".matches("^[\\s&&[^\\n]]*\\n$"));    //以非\n的空白字符开头，出现零次或多次，并且以\n结束的字符串

        p("aaa 8888c".matches(".*\\d{4}."));
        p("aaa 8888c".matches(".*\\b\\d{4}."));
        p("aaa8888c".matches(".*\\d{4}."));
        p("aaa8888c".matches(".*\\b\\d{4}."));
    }

    /**
     * 使用match、find、lookingAt
     */
    private static void aboutMatchFindLookAt() {
        Pattern p = Pattern.compile("\\d{3,5}");
        String s = "123-4567-890-00";
        Matcher m = p.matcher(s);//注意,matcher是全局匹配.这里明显是不匹配.
                                 // 但是,由于s里面的"123"和p是匹配的,
                                 // 所以他会将这三个数字去掉.
                                 // 下次调用匹配方法的时候,是将剩余的字符串来继续匹配
        p(m.matches());
		m.reset();  //重新设置到最开始..如果这里没有这一步,下面的匹配将受到影响...
        p(m.find());//find方法是部分匹配..也就是说,只要找到有匹配的字符段就算匹配...但是,他和matcher方法一样也会将s里面已经匹配的字符去掉....这里匹配的是"123" 
        p(m.start() + "-" + m.end());
        p(m.find());    //剩余的字符
        p(m.start() + "-" + m.end());
        p(m.find());    //剩余的字符
        p(m.start() + "-" + m.end()); //如果找不到就会抛出异常
        p(m.find());    //剩余的字符


        p(m.lookingAt());
        p(m.lookingAt());
        p(m.lookingAt());
        p(m.lookingAt());

        //find是全局匹配，lookingAt是区域匹配
        //start方法访问的是开始匹配的问题.注意,end方法返回的是最后匹配位置的下一个位置
        //位置从0开始
    }

    /**
     * 关于start、end
     */
    private static void aboutStartEnd() {
        Pattern p = Pattern.compile(".{3,10}+[0-9]");
        String s = "aaaa5bbbb68";
        Matcher m = p.matcher(s);
        if (m.find())
            p(m.start() + "-" + m.end());
        else
            p("not match!");
    }

    private static void aboutReplace() {
        Pattern p = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
        Matcher m = p.matcher("java Java JAVa JaVa IloveJAVA you hateJava afasdfasdf");

// 全部替换成大写
        p(m.replaceAll("JAVA"));

// 把找到的单数个串答谢，双数个串小写
        StringBuffer buf = new StringBuffer();
        int i = 0;
        while (m.find()) {
            i++;
            if (i % 2 == 0) {
                m.appendReplacement(buf, "java");
            } else {
                m.appendReplacement(buf, "JAVA");
            }
        }
        m.appendTail(buf);
        p(buf);
    }

    /**
     * 关于分组
     */
    private static void aboutGroup() {
        // 打印出找到的每一个分组。()代表分组
        Pattern p = Pattern.compile("(\\d{3,5})([a-z]{2})");
//        Pattern p = Pattern.compile("\\d{3,5}[a-z]{2}");
        String s = "123aa-34345bb-234cc-00";
        Matcher m = p.matcher(s);
        while (m.find()) {
            p(m.group());       //取所有分组
//            p(m.group(1));    //取第1组
//            p(m.group(2));    //取第2组
        }
    }

    private static void p(Object o) {
        System.out.println(o);
    }
}
